Skip to content

Preserve large integer strings in intcomma - #404

Open
x0Lazarus wants to merge 1 commit into
python-humanize:mainfrom
x0Lazarus:fix/intcomma-large-integer-strings
Open

x0Lazarus wants to merge 1 commit into
python-humanize:mainfrom
x0Lazarus:fix/intcomma-large-integer-strings

Conversation

@x0Lazarus

Copy link
Copy Markdown

intcomma(str(10**400 + 123)) currently returns "+Inf", although the same finite value passed as an integer is formatted correctly. The string path checks float(value) before attempting integer parsing, so values beyond the floating-point range are mistaken for infinity.

With the default precision, parse integer strings with int() first, after normalizing the locale's separators. Inputs that are not integer strings continue through the existing float/non-finite handling. This extends the default-precision behavior fixed for integer inputs in #392 to plain and already-grouped integer strings.

The regression tests cover both signs, preserve the final 123, and check German and French grouping. Compatibility cases retain the existing handling of decimal strings, exponent strings, invalid input, and non-finite values. The existing float check is retained when ndigits is explicitly set, with controls for both signs beyond the float range.

Validation on Windows with Python 3.12:

  • Four plain/grouped string regressions fail on the original source and pass with the change.
  • Focused number and localization tests: 49 passed.
  • Full suite with doctests and benchmark timing disabled: 799 passed, 69 skipped. German, French and Portuguese catalogs were compiled; remaining translation cases and gettext tool checks were skipped.
  • Ruff and Black pass for the three changed files; mypy passes for all 14 source/test files; git diff --check passes.

@hugovk

hugovk commented Sep 20, 2026

Copy link
Copy Markdown
Member

@Voyagerroc-Lab There's no need to use AI to summarise the original PR description.

@hugovk hugovk added the changelog: Fixed For any bug fixes label Sep 20, 2026
@codecov

codecov Bot commented Sep 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.70%. Comparing base (392aef7) to head (6cc366f).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #404   +/-   ##
=======================================
  Coverage   99.69%   99.70%           
=======================================
  Files          12       12           
  Lines         996     1011   +15     
=======================================
+ Hits          993     1008   +15     
  Misses          3        3           
Flag Coverage Δ
macos-latest 97.62% <100.00%> (+0.03%) ⬆️
ubuntu-latest 97.62% <100.00%> (+0.03%) ⬆️
windows-latest 92.77% <70.00%> (-0.50%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@itzzdev09

Copy link
Copy Markdown

Confirmed, and the asymmetry is the convincing part — the same finite value formats correctly or not depending only on whether you hand it over as an int or a str:

>>> big = 10**400 + 123
>>> intcomma(big)        # '10,000,...,123'
>>> intcomma(str(big))   # '+Inf'

Calling float() first to decide finiteness is what does it: the value is perfectly representable as an int, and only becomes infinite because of the conversion performed to inspect it.

I diffed the full behaviour against main rather than just the reported case, and only the broken one moves:

input main this branch
str(10**400 + 123) +Inf 10,000,…,123
'-' + str(10**400+123) +Inf -10,000,…,123
'1234.5' / 1234.5 1,234.5 same
1234.5678 1,234.5678 same
'1,234' 1,234 same
'007' 7 same
'abc', None, '' unchanged same
'1e400' +Inf +Inf

Leaving '1e400' as +Inf is the right call, incidentally — it isn't an integer string, so it legitimately goes down the float path and genuinely is infinite there.

pytest tests/test_number.py gives 253 passed versus 241 on main.

Worth flagging across PRs: this is the same root pattern as #414, which fixes ordinal(10**400) raising OverflowError for exactly the same reason — a float() conversion performed ahead of the integer path, on a value the integer path would have handled. Two functions in number.py, same shape of bug, found independently. It may be worth a look at whether anything else in that module inspects values via float() before trying int(), so the third instance doesn't have to be found by a user.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog: Fixed For any bug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants